package com.g4m.baselib.component;

import com.g4m.baselib.entity.SdkResponse;
import com.g4m.baselib.entity.WebConstants;
import com.netflix.hystrix.exception.HystrixTimeoutException;
import org.slf4j.Logger;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.RejectedExecutionException;

/**
 * haosenwei[haosenwei@hudesen.com]
 * <p>
 * 05/02/2021 00:47
 * <p>Copyright 2008-2019 snsndk.com</p>
 */
public class SdkFeginFactoryProxy implements InvocationHandler {

    private Throwable throwable;
    private Logger logger;

    /**
     * 反编译
     *
     * @param proxy  代理
     * @param method 方法
     * @param args   参数
     * @return res
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        try {
            if (throwable instanceof HystrixTimeoutException) {
                logger.debug("feginRetry,class:{},methed:{},调用超时:{}", method.getDeclaringClass().getName(), method.getName(), throwable.getMessage());
            } else if (throwable instanceof RejectedExecutionException) {
                logger.error("feginReject:{},请求线程池满:{}", method.getName(), throwable.getMessage());
            } else if (throwable instanceof RuntimeException) {
                logger.error("feginRuntimeError:{},发生熔断:{}", method.getName(), throwable);
            } else {
                logger.error("feginError:{},发生错误:{}", method.getName(), throwable);
            }
            return SdkResponse.buildResponse(WebConstants.RESPONSE_RESULT_SYSTEM_ERROR);
        } catch (Exception e) {
            return SdkResponse.buildResponse(WebConstants.RESPONSE_RESULT_SYSTEM_ERROR);
        }
    }

    /**
     * 获取代理类
     *
     * @param mapperInterface 接口
     * @param throwable       异常
     * @param logger          日志
     * @param <T>             泛性
     * @return 泛行
     */
    public static <T> T newMapperProxy(Class<T> mapperInterface, Throwable throwable, Logger logger) {
        ClassLoader classLoader = mapperInterface.getClassLoader();
        Class<?>[] interfaces = new Class[]{mapperInterface};
        SdkFeginFactoryProxy proxy = new SdkFeginFactoryProxy();
        proxy.setThrowable(throwable);
        proxy.setLogger(logger);
        return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
    }

    /**
     * 异常
     *
     * @return 异常
     */
    public Throwable getThrowable() {
        return throwable;
    }

    /**
     * 异常
     *
     * @param throwable 异常
     */
    public void setThrowable(Throwable throwable) {
        this.throwable = throwable;
    }

    /**
     * 日志
     *
     * @return 日志
     */
    public Logger getLogger() {
        return logger;
    }

    /**
     * 日志
     *
     * @param logger 日志
     */
    public void setLogger(Logger logger) {
        this.logger = logger;
    }
}

